package com.amigo.online.provider.ffmpeg.util;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jboss.logging.Logger;
import org.springframework.stereotype.Component;

import com.amigo.online.provider.ffmpeg.common.ConstantValue;

/**
 * 从视频中提取音频
 */
@Component
public class FFMpegUtil {

    private static final Logger logger = Logger.getLogger(FFMpegUtil.class);

    /**
     * 视频抽取音频
     *
     * @param videoUrl
     * @param videoName
     */
    public String videoToAudio(String videoUrl, String videoName) {
        String musicUrl = "";
        try {
            String aacFile = ConstantValue.HOME_PATH + ConstantValue.MUSIC_TMP_PATH + videoName + ".mp3";
            String command = ConstantValue.FFMPEG_PATH + "ffmpeg -i " + videoUrl + " -y -f mp3 -vn " + aacFile;
            logger.info("video to audio command : " + command);
            Process process = Runtime.getRuntime().exec(command);
            // 这里我们需要对流进行处理,防止process.waitFor()方法产生死锁
            InputStream errorStream = process.getErrorStream();
            InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
            BufferedReader br = new BufferedReader(inputStreamReader);
            while (br.readLine() != null) {
            }
            if (br != null) {
                br.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (errorStream != null) {
                errorStream.close();
            }
            process.waitFor();
            File file = new File(aacFile);
            String fileId = FastDFSClient.uploadFile(file);
            if (fileId != null) {
                musicUrl = fileId;
            } else {
                logger.error("音频文件上传失败,音频路径：" + aacFile);
            }
            // 删除临时文件
            Runtime.getRuntime().exec("rm -rf " + aacFile);
            process.destroy();
            // Response res = qiniuUtil.upload(aacFile,videoName+".mp3");
        } catch (Exception e) {
            logger.error("音频提取失败，视频地址：" + videoUrl, e);
        }
        return musicUrl;
    }

    public static final byte[] input2byte(InputStream inStream) throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        return in2b;
    }

    /**
     * @param videoUrl
     * @param videoName
     * @param account
     * @param color
     * @param waterMarkImg
     * @param logo
     * @return
     */
    public String videoAddWaterMark(String videoUrl, String videoName, String account, String color,
                                    String waterMarkImg, String fontsize, String fonttype, int font_x, int font_y, int logo_x, int logo_y) {
        String videoWithwaterMarkUrl = "";
        StringBuilder aacFileBuilder = new StringBuilder(ConstantValue.HOME_PATH).append(ConstantValue.VIDEO_TMP_PATH)
                .append(videoName).append(".mp4");
        StringBuilder commandBuilder = new StringBuilder(ConstantValue.FFMPEG_PATH).append("ffmpeg -y -i ")
                .append(videoUrl).append(" -c:v libx264 -c:a copy -vf ").append("\"[in]drawtext=fontfile=")
                .append(ConstantValue.FONT_TYPE).append(":text='ID\\:").append(account).append("':x=").append(font_x)
                .append(":y=").append(font_y).append(":fontsize=").append(fontsize).append(":fontcolor=white")
                .append(":shadowy=1:shadowcolor=").append(color).append("[text];").append("movie=").append(waterMarkImg)
                .append("[watermark];[text][watermark]overlay=").append(logo_x).append(":").append(logo_y)
                .append("[out]\" ").append(aacFileBuilder);
        System.out.println(commandBuilder.toString());
        try {
            Process process = Runtime.getRuntime().exec(commandBuilder.toString());
            // 这里我们需要对流进行处理,防止process.waitFor()方法产生死锁
            InputStream errorStream = process.getErrorStream();
            InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
            BufferedReader br = new BufferedReader(inputStreamReader);
            while (br.readLine() != null) {
            }
            if (br != null) {
                br.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (errorStream != null) {
                errorStream.close();
            }
            process.waitFor();
            String fileId = FastDFSClient.uploadFile(input2byte(process.getInputStream()), null);
            System.out.println(fileId);
            if (fileId != null) {
                videoWithwaterMarkUrl = fileId;
            } else {
                logger.error("带水印视频文件上传失败,原视频作者ID:" + account + "原视频名:" + videoName);
            }
            // 删除临时文件
            // Runtime.getRuntime().exec("rm -rf " + aacFileBuilder.toString());
            process.destroy();
        } catch (Exception e) {
            logger.error("带水印视频文件提取失败,原视频作者ID:" + account + "原视频名:" + videoName, e);
        }
        return videoWithwaterMarkUrl;
    }

    public synchronized int dealVideoOperation(List<String> command) {
        StringBuilder executeResult = new StringBuilder(10240);
        int time = 0;
        try {
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String result = null;
            while ((result = br.readLine()) != null) {
                executeResult.append(result);
            }
            //Duration: 00:00:10.04, start: 0.000000, bitrate: 649 kb/s
            String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
            Pattern pattern = Pattern.compile(regexDuration);
            Matcher m = pattern.matcher(executeResult.toString());
            if (m.find()) {
                time = getTimelen(m.group(1));
                logger.info("视频时长：" + time + ", 开始时间：" + m.group(2) + ",比特率：" + m.group(3) + "kb/s");
            }
            int rs = process.waitFor();
            process.destroy();
            if (rs != 0) {
                logger.error(executeResult.toString());
                throw new Exception();
            }
        } catch (Exception e) {
            String message = "";
            for (String str: command){
                message+=str + " ";
            }
            logger.error("带水印视频文件提取失败,提取命令为:" + message + " ! 执行结果为:" + executeResult.toString(), e);
        }
        logger.info("水印文件提取成功");
        return time;
    }

    public void removeTempFile(String file) {
        try {
            Runtime.getRuntime().exec("rm -rf " + file);
        } catch (IOException e) {
            logger.error("删除临时文件失败! 失败文件:" + file);
        }
    }

    private static int getTimelen(String timelen) {
        int min = 0;
        String strs[] = timelen.split(":");
        if (strs[0].compareTo("0") > 0) {
            min += Integer.valueOf(strs[0]) * 60 * 60;//秒
        }
        if (strs[1].compareTo("0") > 0) {
            min += Integer.valueOf(strs[1]) * 60;
        }
        if (strs[2].compareTo("0") > 0) {
            min += Math.round(Float.valueOf(strs[2]));
        }
        return min;
    }

}
